﻿using NCalc;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
public class ScriptOne
{
    #region 1分钟

    public static Dictionary<string, Dictionary<string, int>> finalResult = new Dictionary<string, Dictionary<string, int>>();

    public static Dictionary<string, int> toAdjustLevel = new Dictionary<string, int>();


    public static List<string> model_codes = new List<string>();

    public static Dictionary<string, CRule> neededRule = new Dictionary<string, CRule>();

    public static Dictionary<string, double> parametersResult = new Dictionary<string, double>();
    public static bool ConfigureParas()
    {

        // model_codes = neededData["analysisModels"];

        model_codes = AnalysisConfiguration.analysisModels;


        if (neededRule != null)
        {
            neededRule.Clear();
            toAdjustLevel.Clear();
        }

        foreach (string item in model_codes)
        {
            // neededRule.Add(item, settingData[item]);
            //  CRule a = JsonConvert.DeserializeObject<CRule>(settingData[item].ToString());

            var Level2Factor = FactorConfigurations?.SingleOrDefault(t => t.code.Equals(item));
            CRule a = new CRule()
            {
                standard = Level2Factor.standard,
                result = Level2Factor.result,
                formula = Level2Factor.formula,
            };
            neededRule.Add(item, a);

            toAdjustLevel.Add(item, 0);
        }
        return true;

    }


    public static bool correct_condition(double drowsinessLevel, double sleepStage)
    {
        if (drowsinessLevel > 0 || sleepStage == 1 || sleepStage == 2 || sleepStage == 3 || sleepStage == 0)
        {
            return true;
        }
        return false;
    }
    public static string OneMinuteAnalysis(string value_json)
    {

        parametersResult = new Dictionary<string, double>();

        // 解析  一分钟对应的数据  
        //  Dictionary<string, List<int>> settingDataValue = JsonConvert.DeserializeObject<Dictionary<string, List<int>>(value_json);

        parametersResult.Clear();

        Dictionary<string, List<int>> settingDataValue = JsonConvert.DeserializeObject<Dictionary<string, List<int>>>(value_json);
        string result = "{\n";
        foreach (var kvp in settingDataValue)
        {
            result += $"  \"{kvp.Key}\" : [{string.Join(", ", kvp.Value)}],\n";
        }
        result = result.TrimEnd(',', '\n') + "\n}";

        if (result.Contains("-99"))
        {
            foreach (var item in model_codes)
            {
                finalResult[item] = new Dictionary<string, int>()
                 {
               {"score", -1},
               {"level",-1}
                  };
            }

            string offlineData = JsonConvert.SerializeObject(finalResult);
            return offlineData;

        }
        foreach (var item in settingDataValue.Keys)
        {

            if (item == "lfnSet")
            {
                var var1 = settingDataValue[item].Sum(x => x);
                var var2 = settingDataValue[item].Count(x => x == -1);
                var var3 = settingDataValue[item].Count;
                var var4 = (var1 + var2) / (var3 - var2);
                parametersResult.Add("lfn", var4);
            }
            else if (item == "drowsinessLevel" || item == "sleepStage")
            {
                parametersResult.Add(item, settingDataValue[item][settingDataValue[item].Count - 1]);
            }
            else
            {
                string var5 = item.Replace("Set", "");
                parametersResult.Add(var5, settingDataValue[item].Count(x => x == 1));
            }
            // parametersResult.Add(item,)

        }

        foreach (string itemX in neededRule.Keys)
        {
            CalculateCfactor(itemX, neededRule);
        }

        string json = JsonConvert.SerializeObject(finalResult);

        return json;
    }
    public static List<string> FindItemsWithChar(List<string> lst, string str)
    {
        List<string> result = new List<string>();
        foreach (string item in lst)
        {
            if (item.Contains(str))
            {
                result.Add(item);
            }
        }
        return result;
    }

    public static double EvaluateFormula(string someIndex, string formula)
    {
        // Evaluate the formula and return the score

        Expression e = new Expression(formula, EvaluateOptions.IgnoreCase);

        foreach (string item in parametersResult.Keys)
        {
            e.Parameters[item] = parametersResult[item];
        }

        var result = e.Evaluate();


        return (double)result;
    }

    public static int AdjustLevel(string formula)
    {
        // Evaluate the formula and return the score

        Expression e = new Expression(formula, EvaluateOptions.IgnoreCase);

        foreach (string item in toAdjustLevel.Keys)
        {
            e.Parameters[item] = toAdjustLevel[item];
        }

        var result = e.Evaluate();


        return (int)result;
    }
    public static void CalculateCfactor(string variable, Dictionary<string, CRule> modelSettingData)
    {
        List<string> correct_result = new List<string>()
             {
            "Max(energyStatus - 1, 1)",
            "Max(effortLevel - 1, 1)",
            "Max(focusOnInvestment - 1, 1)",
            "Max(enterprising - 1, 1)",
            "Min(easyObedient + 1, 3)",
            "Min(emotionManager + 1, 3)",
            "Min(fatigueStatus + 2, 5)"
             };
        double score = EvaluateFormula(variable, modelSettingData[variable].formula);

        score = ModifyScore(score);

        string[] standard = modelSettingData[variable].standard.Split('|');
        string[] result = modelSettingData[variable].result.Split('|');
        int resultLevel = 0;
        for (int i = 0; i < standard.Length; i++)
        {
            if (score <= double.Parse(standard[i]))
            {
                resultLevel = int.Parse(result[i]);
                break;
            }
        }
        if (resultLevel == 0)
        {
            resultLevel = int.Parse(result[result.Length - 1]);
        }

        toAdjustLevel[variable] = resultLevel;
        //

        if (correct_condition(parametersResult["drowsinessLevel"], parametersResult["sleepStage"]))
        {
            List<string> result2 = FindItemsWithChar(correct_result, variable);
            if (result2.Count > 0)
            {
                resultLevel = AdjustLevel(result2[0]);
            }
        }

        finalResult[variable] = new Dictionary<string, int>()
          {
        {"score", (int)score},
        {"level", resultLevel}
           };

    }

    public static double ModifyScore(double score)
    {
        if (score < 0)
        {
            score = 20 - Math.Log(Math.Abs(score) + 1);
        }
        else if (score >= 99)
        {
            score = 90 + Math.Log(score - 99 + 1);
        }
        double score_f = Math.Round(score, MidpointRounding.AwayFromZero);
        return score_f;
    }
    #endregion
    #region 15分钟

    static string periodStatus = string.Empty;
    public static Random random = new Random();

    //状态列表
    public static List<string> status = new List<string>();
    public static List<string> up_event = new List<string>();
    public static List<string> down_event = new List<string>();

    //"statusCodes":["positive","serious","normal","common","relax","rest"],"statusScore":[6,5,4,3,2,1],
    public static List<string> status_codes = new List<string>();
    public static List<int> status_score = new List<int>();
    public static Dictionary<string, string> variables = new Dictionary<string, string>();
    public static List<string> randoms = new List<string>();
    public static Dictionary<string, string> none_opts = new Dictionary<string, string>();
    public static string offline_des = "期间出现较长时间断线，评估结果仅供参考。";




    static void parse_status_for_period()
    {


        //返回的字符串的总模板
        var statusQualitative = ModelConfigurations?.SingleOrDefault(t => t.code.Equals("periodStatus"));
        periodStatus = statusQualitative.related_cfactors.ToString();



        //已经获得Status_codes 
        status_codes = AnalysisConfiguration.statusCodes;
        status_codes.Remove("-1");

        List<string> modelList = AnalysisConfiguration.analysisModels;


        if (status_score.Count != 0)
        {
            status_score.Clear();
        }

        // 获取配置的statusScore

        var sModelScore = FactorConfigurations?.SingleOrDefault(t => t.code.Equals("statusScore"));


        List<double> paraScores3 = sModelScore.standards;  //list<Score>

        List<object> paraStatusStr3 = sModelScore.results;

        List<string> paraScores = sModelScore.standard.Split('|').ToList();  //list<Score>

        //   List<string> list_result = JsonConvert.DeserializeObject<List<string>>(result);

        //   List<string> x8 = sModelScore.result.Split('|').ToList();
        //   List<string> x9 = new List<string>();

        //    sModelScore.result = sModelScore.result.Replace("[\"", "").Replace("\"]", "");


        //  List<string> paraStatusStr = sModelScore.result.Split('|').ToList();
        //      List<string> paraStatusStr = sModelScore.results.OfType<string>().ToList();
        List<string> paraStatusStr = new List<string>();

        foreach (object itemX in paraStatusStr3)
        {
            paraStatusStr.Add(((List<string>)itemX)[0]);
        }
        List<int> scoreList = paraScores.ConvertAll(int.Parse);

        for (int i = 0; i < status_codes.Count; i++)
        {

            for (int j = 0; j < paraStatusStr.Count; j++)
            {
                if (status_codes[i] == paraStatusStr[j])
                {
                    status_score.Add(scoreList[j]);
                    break;
                }
            }

        }

    }


    public static string AnalysisModel(string value_json)
    {
        try
        {
            //先清
            status.Clear();
            up_event.Clear();
            down_event.Clear();
            none_opts.Clear();
            randoms.Clear();
            var offline_status = ParseStatusAndEvent(value_json);

            if (offline_status == "long_offline")
            {
                var result333_json = new Dictionary<string, string> { { "period_des", "断线时间较长，不做评价" } };
                return result333_json["period_des"];
            }
            ParseSetting();
            CalculateStatus();
            CalculateKeyEvent();
            CalculateExtEvent();
            //   var model_code = setting_data_global["model_code"]["result"];
            var model_code = periodStatus;
            model_code = model_code.Replace("{frequence}", "");
            var final_result = model_code;


            final_result = final_result.Replace("{" + "keyevent" + "}", variables["keyevent"]);
            final_result = final_result.Replace("{" + "extevent" + "}", variables["extevent"]);
            if (none_opts.ContainsKey("key_event"))
            {
                var start_index = final_result.IndexOf("其中");
                var end_index = final_result.IndexOf("，", start_index);
                final_result = final_result.Substring(0, start_index - 1) + final_result.Substring(end_index);
            }
            if (none_opts.ContainsKey("ext_event"))
            {
                var start_index = final_result.IndexOf("并伴随");
                final_result = final_result.Substring(0, start_index - 1) + final_result.Substring(start_index + 3);
            }

            foreach (var variable in variables)
            {
                final_result = final_result.Replace("{" + variable.Key + "}", variable.Value);
            }

            if (offline_status == "part_offline")
            {
                final_result = final_result + offline_des;
            }
            var result_json = new Dictionary<string, string> { { "period_des", final_result } };
            Console.WriteLine(result_json["period_des"]);

            return result_json["period_des"];
        }
        catch (Exception e)
        {
            Console.WriteLine("fail");
            return "fail";
        }
    }


    public static string GetRandom(string result)
    {

        //   List<string> list_result = result.Split(',').ToList();
        List<string> list_result = JsonConvert.DeserializeObject<List<string>>(result);
        if (randoms.Count > 0)
        {
            var var = list_result.Except(randoms).ToList();
            if (var.Count == 0)
            {
                var value = list_result[random.Next(list_result.Count)];
                return value;
            }
            else
            {
                var value = var[random.Next(var.Count)];
                return value;
            }
        }
        else
        {
            var value = list_result[random.Next(list_result.Count)];
            randoms.Add(value);
            return value;
        }
    }


    public static void GetTrend(string variable, float slope)
    {
        var trend1 = FactorConfigurations?.SingleOrDefault(t => t.code.Equals(variable + "_trend"));
        var standard = trend1.standard.Split('|').ToList();
        var result = trend1.result.Split('|').ToList();


        var final_result = "";
        for (int i = 0; i < standard.Count; i++)
        {
            if (slope <= float.Parse(standard[i]))
            {
                final_result = result[i];
                break;
            }
        }
        if (final_result == "")
        {
            final_result = result[result.Count - 1];
        }

        variables[variable + "_trend"] = GetRandom(final_result);   //插入字典项 
    }

    public static string GetFrequence(float frequence)
    {
        //var trend = setting_data["frequence"];
        var trend = FactorConfigurations?.SingleOrDefault(t => t.code.Equals("frequence"));

        var standard = trend.standard.Split('|').ToList();
        var result = trend.result.Split('|').ToList();
        var final_result = "";
        for (int i = 0; i < standard.Count; i++)
        {
            if (frequence <= float.Parse(standard[i]))
            {
                final_result = result[i];
                break;
            }
        }
        if (final_result == "")
        {
            final_result = result[result.Count - 1];
        }

        //       var xx = FactorConfigurations?.SingleOrDefault(t => t.code.Equals("totaldes")).result.Replace("\"", "").Replace("[", "").Replace("]", "");
        return GetRandom(final_result);
    }

    public static void CalculateStatus()
    {

        var status_dict = status_codes.Zip(status_score, (k, v) => new { k, v }).ToDictionary(x => x.k, x => x.v);

        var total_score = status.Sum(s => status_dict[s]);

        int average_score = (int)Math.Round((float)total_score / status.Count, MidpointRounding.AwayFromZero);


        var status_slope = (status_dict[status.Last()] - status_dict[status.First()]) * 1.0f / status.Count;

        var final_status = status_dict.FirstOrDefault(x => x.Value == average_score).Key;
        variables["status"] = final_status;      //字典变量插入或更新
        GetTrend("status", status_slope);

    }

    public static void CalculateKeyEvent()
    {

        var counter = up_event.GroupBy(x => x).ToDictionary(x => x.Key, x => x.Count());

        var most_common_three = counter.OrderByDescending(x => x.Value).Take(3).ToList();
        if (most_common_three.Count == 0)
        {
            none_opts["key_event"] = "1";
        }

        var keys = new List<string>();
        var total_count = status.Count;
        foreach (var item in most_common_three)
        {
            var pctg = (float)item.Value / total_count * 100;
            keys.Add(GetFrequence(pctg) + "的{" + item.Key + "}");
        }
        var result = string.Join("、", keys);
        variables["keyevent"] = result;

    }

    public static void CalculateExtEvent()
    {

        var counter = down_event.GroupBy(x => x).ToDictionary(x => x.Key, x => x.Count());

        var most_common_three = counter.OrderByDescending(x => x.Value).Take(3).ToList();
        if (most_common_three.Count == 0)
        {
            none_opts["ext_event"] = "1";
        }

        var keys = new List<string>();
        var total_count = status.Count;
        foreach (var item in most_common_three)
        {
            var pctg = (float)item.Value / total_count * 100;
            keys.Add(GetFrequence(pctg) + "的{" + item.Key + "}");
        }
        var result = string.Join("、", keys);
        variables["extevent"] = result;

    }


    public static string ParseStatusAndEvent(string value_json)
    {
        var count = 0;


        List<StatusEvent> threeResults = new List<StatusEvent>();
        threeResults = JsonConvert.DeserializeObject<List<StatusEvent>>(value_json);
        if (threeResults.Count != 0)
        {
            foreach (var item in threeResults)
            {
                if (item.status != "-1")
                {
                    status.Add(item.status);

                    foreach (var eventPoint in item.eventPoint)
                    {
                        if (eventPoint.up != null)
                        {
                            foreach (var itemX3 in eventPoint.up)
                            {
                                up_event.Add(itemX3.eventCode);
                            }
                        }
                        else if (eventPoint.down != null)
                        {
                            foreach (var itemX3 in eventPoint.down)
                            {
                                down_event.Add(itemX3.eventCode);
                            }
                        }

                    }
                    count += 1;
                }

            }
        }



        var percetage = count * 100 / threeResults.Count;
        if (percetage < 10)
        {
            return "long_offline";
        }
        else if (percetage < 50)
        {
            return "part_offline";
        }
        else
        {
            return "";
        }
    }



    public static void ParseSetting()
    {
        //  //   GetRandom(item.Value["result"]);
        //var xx=  FactorConfigurations?.SingleOrDefault(t => t.code.Equals("totaldes")).result;
        //  var xxxx = JsonConvert.DeserializeObject<List<string>>(xx);
        //  variables["totaldes"] = GetRandomFromList(xxxx);        

        variables["totaldes"] = GetRandom(FactorConfigurations?.SingleOrDefault(t => t.code.Equals("totaldes")).result);

        variables["predicate1"] = GetRandom(FactorConfigurations?.SingleOrDefault(t => t.code.Equals("predicate1")).result);

        variables["predicate2"] = GetRandom(FactorConfigurations?.SingleOrDefault(t => t.code.Equals("predicate2")).result);

        variables["connect"] = GetRandom(FactorConfigurations?.SingleOrDefault(t => t.code.Equals("connect")).result);

        variables["difficult"] = GetRandom(FactorConfigurations?.SingleOrDefault(t => t.code.Equals("difficult")).result);
        variables["detail"] = GetRandom(FactorConfigurations?.SingleOrDefault(t => t.code.Equals("detail")).result);
        variables["thinking"] = GetRandom(FactorConfigurations?.SingleOrDefault(t => t.code.Equals("thinking")).result);
        variables["focus"] = GetRandom(FactorConfigurations?.SingleOrDefault(t => t.code.Equals("focus")).result);
        variables["downcast"] = GetRandom(FactorConfigurations?.SingleOrDefault(t => t.code.Equals("downcast")).result);
        variables["nervous"] = GetRandom(FactorConfigurations?.SingleOrDefault(t => t.code.Equals("nervous")).result);
        variables["fatigue"] = GetRandom(FactorConfigurations?.SingleOrDefault(t => t.code.Equals("fatigue")).result);
        variables["helpless"] = GetRandom(FactorConfigurations?.SingleOrDefault(t => t.code.Equals("helpless")).result);
        variables["worry"] = GetRandom(FactorConfigurations?.SingleOrDefault(t => t.code.Equals("worry")).result);
        variables["emotion"] = GetRandom(FactorConfigurations?.SingleOrDefault(t => t.code.Equals("emotion")).result);
        variables["excite"] = GetRandom(FactorConfigurations?.SingleOrDefault(t => t.code.Equals("excite")).result);
    }
    #endregion
}
public class CRule
    {
        public string standard { get; set; }
        public string result { get; set; }
        public string formula { get; set; }
    }
 public class Result
    {
        public int score { get; set; }
        public int level { get; set; }
    }
public class EventDetail
{
    public string eventCode { get; set; }
    public int index { get; set; }
}

public class EventPoint
{
    public List<EventDetail> up { get; set; }
    public List<EventDetail> down { get; set; }
}

public class StatusEvent
{
    public string status { get; set; }
    public List<EventPoint> eventPoint { get; set; }
}


